import json
import os
import ssl
import typing
from pathlib import Path
import datetime

from CAAi3dxClient import CAAi3dxClient
from CAAi3dxGetWebServicesClient import CAAi3dxGetWebServicesClient
from CAAi3dxLoginClient import CAAi3dxLoginClient
from CAAi3dxPostWebServicesClient import CAAi3dxPostWebServicesClient
from CAAi3dxPutWebServicesClient import CAAi3dxPutWebServicesClient

import sys


def disable_ssl_verification():
    # Disable SSL certificate verification (unsafe for production)
    ssl._create_default_https_context = ssl._create_unverified_context


class Logger:
    def __init__(self, output_dir: str = None):
        self.output_dir = output_dir
        self.log_file = None
        self.original_stdout = None
        self.original_stderr = None

        if output_dir:
            self._setup_logging()

    def _setup_logging(self):
        """设置日志文件"""
        try:
            log_dir = Path(self.output_dir) / "logs"
            log_dir.mkdir(parents=True, exist_ok=True)

            date_str = datetime.datetime.now().strftime('%Y%m%d')
            self.log_file = log_dir / f"remote_request_{date_str}.log"

            # 重定向标准输出和错误输出到日志文件
            self.original_stdout = sys.stdout
            self.original_stderr = sys.stderr

            # 创建一个同时输出到控制台和文件的流
            class TeeOutput:
                def __init__(self, original_stream, log_file):
                    self.original_stream = original_stream
                    self.log_file = log_file

                def write(self, text):
                    self.original_stream.write(text)
                    if self.log_file:
                        with open(self.log_file, 'a', encoding='utf-8') as f:
                            f.write(text)

                def flush(self):
                    self.original_stream.flush()

            sys.stdout = TeeOutput(sys.stdout, self.log_file)
            sys.stderr = TeeOutput(sys.stderr, self.log_file)

            print(f"=== 远程请求日志开始 {datetime.datetime.now()} ===")
            print(f"日志文件: {self.log_file}")

        except Exception as e:
            print(f"设置日志文件失败: {e}")

    def restore(self):
        """恢复原始输出流"""
        if self.original_stdout:
            sys.stdout = self.original_stdout
        if self.original_stderr:
            sys.stderr = self.original_stderr
        if self.log_file:
            print(f"=== 远程请求日志结束 {datetime.datetime.now()} ===")


# get 请求不带 csrf 的批量调用
def GET(host, username, password, app_path_list: [], csrf: bool = False, output_dir: str = None) -> []:
    logger = Logger(output_dir)

    try:
        # Setting up SSL verification bypass (use with caution)
        disable_ssl_verification()

        # Define the necessary parameters (example)
        pass3ds_server = f"{host}/3dpassport"

        space3ds_server = f"{host}/3dspace"
        # security_context = "VPLMProjectLeader.Company Name.Common Space"
        output_dir = "D:/"  # 暂时先留着，以后用来debug

        print("## Getting input arguments:")
        print(f"catch 3DPassport URL={pass3ds_server}")
        print(f"catch user login={username}")
        print(f"catch user password={password}")
        print(f"catch 3DSpace URL={space3ds_server}")
        print(f"catch output directory={output_dir}")
        print("## End Of arguments")

        # Create client instances
        client = CAAi3dxClient(space3ds_server, pass3ds_server, output_dir)
        client_login = CAAi3dxLoginClient(client)
        client_get_ws = CAAi3dxGetWebServicesClient(client)

        # Step 1: Login
        print("## Login")
        os.environ['HTTP_PROXY'] = ''
        os.environ['HTTPS_PROXY'] = ''
        client_login.login(username, password)

        # Step 2: 3DSpace Web Service Call
        print("## Consume 3DSpace Web Service")
        rsList = []
        for app_path in app_path_list:
            res_str = client_get_ws.run(app_path)
            rsList.append(res_str)

        # 写入文件（覆盖原有内容）
        # with open("C:\\Users\\Administrator\\Desktop\\weboutput1.txt", "w", encoding="utf-8") as file:
        #     file.write(res_str)

        # Step 3: Logout
        print("## Logout")
        client_login.logout()

        return rsList
    finally:
        logger.restore()


def POST(host, username, password, app_path, body: typing.Dict, csrf: bool = False, output_dir: str = None):
    logger = Logger(output_dir)

    try:
        # Setting up SSL verification bypass (use with caution)
        disable_ssl_verification()

        # Define the necessary parameters (example)
        pass3ds_server = f"{host}/3dpassport"

        space3ds_server = f"{host}/3dspace"
        # security_context = "VPLMProjectLeader.Company Name.Common Space"
        output_dir = "D:/"  # 暂时先留着，以后用来debug

        print("## Getting input arguments:")
        print(f"catch 3DPassport URL={pass3ds_server}")
        print(f"catch user login={username}")
        print(f"catch user password={password}")
        print(f"catch 3DSpace URL={space3ds_server}")
        print(f"catch output directory={output_dir}")
        print("## End Of arguments")

        # Create client instances
        client = CAAi3dxClient(space3ds_server, pass3ds_server, output_dir)
        client_login = CAAi3dxLoginClient(client)
        client_post_ws = CAAi3dxPostWebServicesClient(client)

        # Step 1: Login
        print("## Login")
        os.environ['HTTP_PROXY'] = ''
        os.environ['HTTPS_PROXY'] = ''
        client_login.login(username, password)

        # Step 2: 3DSpace Web Service Call
        print("## Consume 3DSpace Web Service")

        res_str = client_post_ws.run(app_path, body)

        # 写入文件（覆盖原有内容）
        # with open("C:\\Users\\Administrator\\Desktop\\weboutput1.txt", "w", encoding="utf-8") as file:
        #     file.write(res_str)

        # Step 3: Logout
        print("## Logout")
        client_login.logout()

        return res_str
    finally:
        logger.restore()


def POSTFile(host, username, password, app_path, body: bytes, csrf: bool = False, output_dir: str = None):
    logger = Logger(output_dir)

    try:

        # Setting up SSL verification bypass (use with caution)
        disable_ssl_verification()

        # Define the necessary parameters (example)
        pass3ds_server = f"{host}/3dpassport"

        space3ds_server = f"{host}/3dspace"
        # security_context = "VPLMProjectLeader.Company Name.Common Space"
        output_dir = "D:/"  # 暂时先留着，以后用来debug

        print("## Getting input arguments:")
        print(f"catch 3DPassport URL={pass3ds_server}")
        print(f"catch user login={username}")
        print(f"catch user password={password}")
        print(f"catch 3DSpace URL={space3ds_server}")
        print(f"catch output directory={output_dir}")
        print("## End Of arguments")

        # Create client instances
        client = CAAi3dxClient(space3ds_server, pass3ds_server, output_dir)
        client_login = CAAi3dxLoginClient(client)
        client_post_ws = CAAi3dxPostWebServicesClient(client)

        # Step 1: Login
        print("## Login")
        os.environ['HTTP_PROXY'] = ''
        os.environ['HTTPS_PROXY'] = ''
        client_login.login(username, password)

        # Step 2: 3DSpace Web Service Call
        print("## Consume 3DSpace Web Service")

        res_str = client_post_ws.runUpload(app_path, body)

        # 写入文件（覆盖原有内容）
        # with open("C:\\Users\\Administrator\\Desktop\\weboutput1.txt", "w", encoding="utf-8") as file:
        #     file.write(res_str)

        # Step 3: Logout
        print("## Logout")
        client_login.logout()

        return res_str
    finally:
        logger.restore()


def PUT(host, username, password, app_path: str, body: typing.Dict, csrf: bool = True, output_dir: str = None):
    logger = Logger(output_dir)

    try:
        # Setting up SSL verification bypass (use with caution)
        disable_ssl_verification()

        # Define the necessary parameters (example)
        pass3ds_server = f"{host}/3dpassport"

        space3ds_server = f"{host}/3dspace"
        # security_context = "VPLMProjectLeader.Company Name.Common Space"
        output_dir = "D:/"  # 暂时先留着，以后用来debug

        print("## Getting input arguments:")
        print(f"catch 3DPassport URL={pass3ds_server}")
        print(f"catch user login={username}")
        print(f"catch user password={password}")
        print(f"catch 3DSpace URL={space3ds_server}")
        print(f"catch output directory={output_dir}")
        print("## End Of arguments")

        # Create client instances
        client = CAAi3dxClient(space3ds_server, pass3ds_server, output_dir)
        client_login = CAAi3dxLoginClient(client)
        client_put_ws = CAAi3dxPutWebServicesClient(client)

        # Step 1: Login
        print("## Login")
        os.environ['HTTP_PROXY'] = ''
        os.environ['HTTPS_PROXY'] = ''
        client_login.login(username, password)

        # Step 2: 3DSpace Web Service Call
        print("## Consume 3DSpace Web Service")

        res_str = client_put_ws.run(app_path, body, csrf)

        # 写入文件（覆盖原有内容）
        # with open("C:\\Users\\Administrator\\Desktop\\weboutput1.txt", "w", encoding="utf-8") as file:
        #     file.write(res_str)

        # Step 3: Logout
        print("## Logout")
        client_login.logout()

        return res_str
    finally:
        logger.restore()


# 不要但单独使用，这个只是demo，因为是单独登录获取到的cookie然后登出了
def getCSRF(host, username, password) -> str:
    urlCSRF = '/resources/v1/application/CSRF'
    appPathList = [urlCSRF]
    rs = GET(host, username, password, appPathList)
    if len(rs) <= 0:
        raise Exception("No CSRF token")
    rsStr = rs[0]
    rsJson = json.loads(rsStr)
    return rsJson['csrf']['value']


def testGetPrd():
    prd = "prd-58803944-00000666"
    url = f"/resources/v1/modeler/dseng/dseng:EngItem/search?$searchStr={prd}"
    appPathList = [url]
    host = 'https://3de.r2025x.com'
    username = "admin_platform"
    password = "Aa123456"
    getRs = GET(host, username, password, appPathList)
    for rs in getRs:
        print(rs)


def testGetChangeActions():
    # prd = "CA-58803944-00000024"
    # url = f"/resources/v1/modeler/dslc/changeaction/search?$searchStr={prd}"
    # url = f"/resources/v1/modeler/dslc/changeaction/search"
    url = f"/resources/v1/modeler/dslc/changeaction/5FE882295112000067FF737E0000002D"
    appPathList = [url]
    host = 'https://3de.r2025x.com'
    username = "admin_platform"
    password = "Aa123456"
    getRs = GET(host, username, password, appPathList)
    for rs in getRs:
        print(rs)


def testGetProcess():
    prd = "hop-58803944-00000002"
    # url = f"/resources/v1/modeler/dsprcs/dsprcs:MfgOperation/search"
    url = f"/resources/v1/modeler/dsprcs/dsprcs:MfgOperation/E6081E1D00008F7867F90188000103D9"
    appPathList = [url]
    host = 'https://3de.r2025x.com'
    username = "admin_platform"
    password = "Aa123456"
    getRs = GET(host, username, password, appPathList)
    for rs in getRs:
        print(rs)


def testGetChange():
    prd = "hop-58803944-00000002"
    # url = f"/resources/v1/modeler/dsprcs/dsprcs:MfgOperation/search"
    url = f"/resources/caasample/basicrestws/GetChangeDocuments?type=*&name={prd}&revision=*&functionality=isChangeActionTab"
    appPathList = [url]
    host = 'https://3de.r2025x.com'
    username = "admin_platform"
    password = "Aa123456"
    getRs = GET(host, username, password, appPathList)
    for rs in getRs:
        print(rs)


def testGetDocuments():
    # iApp_path1 = "/resources/caasample/basicrestws/GetBOPDocuments?type=DELLmiHeaderOperationReference&name=hop-58803944-00000002&revision=A&relation=Reference+Document";
    # iApp_path2 = "/resources/caasample/basicrestws/GetBOPDocuments?type=DELLmiHeaderOperationReference&name=hop-58803944-00000002&revision=A&relation=SpecificationDocument";
    # iApp_path = "/resources/caasample/basicrestws/GetBOPDocuments?type=DELLmiGeneralOperationReference&name=gop-58803944-00000002&revision=A&relation=Reference+Document";
    # appPathList = [iApp_path1, iApp_path2]
    iApp_path1 = '/resources/modeler/pno/person?current=true&select=preferredcredentials&select=collabspaces'
    appPathList = [iApp_path1]
    host = 'https://3de.r2025x.com'
    username = "admin_platform"
    password = "Aa123456"
    # csrf = getCSRF(host, username, password)
    # print(csrf)
    getRs = GET(host, username, password, appPathList)
    for rs in getRs:
        print(rs)


if __name__ == "__main__":
    # iApp_path = "/DSISTools/Find"
    # testGetDocuments()
    testGetChange()
    # testGetChangeActions()
    # testGetChangeActions()
